package com.ruoyi.factorydata.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.factorydata.domain.MaterialInventory;
import com.ruoyi.factorydata.domain.StockOutOrder;
import com.ruoyi.factorydata.domain.StockOutOrderDetail;
import com.ruoyi.factorydata.mapper.MaterialInventoryMapper;
import com.ruoyi.factorydata.mapper.StockOutOrderDetailMapper;
import com.ruoyi.factorydata.mapper.StockOutOrderMapper;
import com.ruoyi.factorydata.service.IMaterialInventoryService;
import com.ruoyi.factorydata.service.IStockOutOrderService;
import com.ruoyi.system.service.ISysUserService;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 出库单Service业务层处理
 *
 * @author ruoyi
 * @date 2025-08-26
 */
@Service
public class StockOutOrderServiceImpl extends ServiceImpl<StockOutOrderMapper, StockOutOrder> implements IStockOutOrderService {

    private final StockOutOrderMapper stockOutOrderMapper;
    private final MaterialInventoryMapper materialInventoryMapper;
    private final StockOutOrderDetailMapper stockOutOrderDetailMapper;
    private final ISysUserService sysUserService;
    private final IMaterialInventoryService materialInventoryService;

    public StockOutOrderServiceImpl(StockOutOrderMapper stockOutOrderMapper,
                                    MaterialInventoryMapper materialInventoryMapper,
                                    StockOutOrderDetailMapper stockOutOrderDetailMapper,
                                    ISysUserService sysUserService,
                                    IMaterialInventoryService materialInventoryService) {
        this.stockOutOrderMapper = stockOutOrderMapper;
        this.materialInventoryMapper = materialInventoryMapper;
        this.stockOutOrderDetailMapper = stockOutOrderDetailMapper;
        this.sysUserService = sysUserService;
        this.materialInventoryService = materialInventoryService;
    }

    /**
     * 查询出库单
     *
     * @param id 出库单主键
     * @return 出库单
     */
    @Override
    public StockOutOrder selectStockOutOrderById(Long id) {
        StockOutOrder stockOutOrder = stockOutOrderMapper.selectStockOutOrderById(id);
        Map<Long, String> createByCache = new HashMap<>();

        String requisitionUserName = sysUserService.getUserNameByIdAndCache(stockOutOrder.getRequisitionUserId(), createByCache);
        String updateByName = stockOutOrder.getUpdateBy() == null ? null : sysUserService.getUserNameByIdAndCache(Long.parseLong(stockOutOrder.getUpdateBy()), createByCache);
        stockOutOrder.setRequisitionUserName(requisitionUserName);
        stockOutOrder.setUpdateByName(updateByName);
        return stockOutOrder;
    }

    /**
     * 查询出库单列表
     *
     * @param stockOutOrder 出库单
     * @return 出库单
     */
    @Override
    public List<StockOutOrder> selectStockOutOrderList(StockOutOrder stockOutOrder) {
        HashMap<Long, String> createByCache = new HashMap<>();
        return stockOutOrderMapper.selectStockOutOrderList(stockOutOrder)
                .stream()
                .peek(order -> {
                    Long applyNum=stockOutOrderDetailMapper.getApplyNum(order.getId());
                    applyNum=applyNum==null?0L:applyNum;
                    String requisitionUserName = sysUserService.getUserNameByIdAndCache(order.getRequisitionUserId(), createByCache);
                    String updateByName = sysUserService.getUserNameByIdAndCache(order.getUpdateBy()==null?null:Long.parseLong(order.getUpdateBy()), createByCache);

                    order.setRequisitionQuantity(applyNum);
                    order.setRequisitionUserName(requisitionUserName);
                    order.setUpdateByName(updateByName);
                }).collect(Collectors.toList());
    }

    /**
     * 新增出库单
     *
     * @param stockOutOrder 出库单
     * @return 结果
     */
    @Override
    @Transactional
    public int insertStockOutOrder(StockOutOrder stockOutOrder) {
        stockOutOrder.setOrderNo("SCO" + DateFormatUtils.format(new Date(), "yyyyMMddHHmmss"));
        stockOutOrder.setStatus(0);
        stockOutOrder.setCreateBy(SecurityUtils.getUserId() + "");
        stockOutOrder.setCreateTime(DateUtils.getNowDate());
        int save = stockOutOrderMapper.insertStockOutOrder(stockOutOrder);
        if (save > 0) {
            stockOutOrder.getStockOutOrderDetailList()
                    .forEach(detail -> {
                        Long materialInventory = materialInventoryMapper.countMaterialInventoryList(MaterialInventory.builder()
                                .materialId(detail.getMaterialId())
                                .build());
                        StockOutOrderDetail orderDetail = StockOutOrderDetail.builder()
                                .type(1)
                                .orderId(stockOutOrder.getId())
                                .orderNo(stockOutOrder.getOrderNo())
                                .materialId(detail.getMaterialId())
                                .materialCode(detail.getMaterialCode())
                                .materialName(detail.getMaterialName())
                                .materialType(detail.getMaterialType())
                                .materialSpecification(detail.getMaterialSpecification())
                                .materialUnit(detail.getMaterialUnit())
                                .materialUnitName(detail.getMaterialUnitName())
                                .materialCategoryId(detail.getMaterialCategoryId())
                                .manufacturingMethod(detail.getManufacturingMethod())
                                .modelSource(detail.getModelSource())
                                .modelNumber(detail.getModelNumber())
                                .requiredQuantity(detail.getRequiredQuantity())
                                .inventoryQuantity(BigDecimal.valueOf(Optional.ofNullable(materialInventory).orElse(0L)))
                                .receivedQuantity(BigDecimal.ZERO)
                                .shortageQuantity(BigDecimal.ZERO)
                                .returnedQuantity(BigDecimal.ZERO)
                                .build();
                        orderDetail.setCreateTime(DateUtils.getNowDate());
                        orderDetail.setRemark(stockOutOrder.getRemark());
                        orderDetail.setCreateBy(stockOutOrder.getCreateBy());
                        stockOutOrderDetailMapper.insertStockOutOrderDetail(orderDetail);
                    });
        }
        return save;
    }

    /**
     * 修改出库单
     *
     * @param stockOutOrder 出库单
     * @return 结果
     */
    @Override
    public int updateStockOutOrder(StockOutOrder stockOutOrder) {
        stockOutOrder.setUpdateTime(DateUtils.getNowDate());
        return stockOutOrderMapper.updateStockOutOrder(stockOutOrder);
    }

    /**
     * 批量删除出库单
     *
     * @param ids 需要删除的出库单主键
     * @return 结果
     */
    @Override
    public int deleteStockOutOrderByIds(Long[] ids) {
        return stockOutOrderMapper.deleteStockOutOrderByIds(ids);
    }

    /**
     * 删除出库单信息
     *
     * @param id 出库单主键
     * @return 结果
     */
    @Override
    public int deleteStockOutOrderById(Long id) {
        return stockOutOrderMapper.deleteStockOutOrderById(id);
    }

    @Override
    @Transactional
    public int authRequest(StockOutOrder stockOutOrder) {
        StockOutOrder requisition = selectStockOutOrderById(stockOutOrder.getId());
        Assert.isTrue(requisition != null, "当前出库单不存在");
        Assert.isTrue(requisition.getStatus() == 0, "当前状态无法操作");
        stockOutOrder.setStatus(1);
        stockOutOrder.setUpdateTime(DateUtils.getNowDate());
        stockOutOrder.setUpdateBy(SecurityUtils.getUserId() + "");
        int update = updateStockOutOrder(stockOutOrder);
        if (update > 0) {
            List<StockOutOrderDetail> stockOutOrderDetails = stockOutOrder.getStockOutOrderDetailList();
            for (StockOutOrderDetail detail : stockOutOrderDetails) {
                BigDecimal receivedQuantity = BigDecimal.ZERO;
                //批次编号审批：物料批次编号|出库数量,母版批次编号|出库数量
                if (StringUtils.isNotBlank(detail.getBatchNumberStr())) {
                    String[] batchArr = detail.getBatchNumberStr().split(",");
                    for (String batch : batchArr) {
                        String[] batchNumberArr = batch.split("\\|");
                        String inventoryBatchNumber = batchNumberArr[0];
                        BigDecimal inventoryQuantity = new BigDecimal(batchNumberArr[1]);
                        receivedQuantity = receivedQuantity.add(inventoryQuantity);
                        //扣除对应物料库存
                        detail.setRemark(requisition.getRemark());
                        if (detail.getType() == 1) {
                            materialInventoryService.saveInventoryOut(detail, inventoryBatchNumber, inventoryQuantity);
                        }
                    }
                }
                detail.setUpdateBy(SecurityUtils.getUserId() + "");
                detail.setUpdateTime(DateUtils.getNowDate());
                detail.setBatchNumber(detail.getBatchNumberStr());
                detail.setReceivedQuantity(receivedQuantity);
                detail.setShortageQuantity(receivedQuantity.compareTo(detail.getRequiredQuantity()) >= 0 ? BigDecimal.ZERO : detail.getRequiredQuantity().subtract(receivedQuantity));
                update = stockOutOrderDetailMapper.updateStockOutOrderDetail(detail);
                Assert.isTrue(update > 0, "领料单明细保存失败");
            }
        }
        return update;
    }

    @Override
    public int refuseRequest(StockOutOrder stockOutOrder) {
        StockOutOrder requisition = selectStockOutOrderById(stockOutOrder.getId());
        Assert.isTrue(requisition != null, "当前出库单不存在");
        Assert.isTrue(requisition.getStatus() == 0, "当前状态无法拒绝");
        StockOutOrder update = new StockOutOrder();
        update.setId(requisition.getId());
        update.setStatus(-1);
        update.setRemark(stockOutOrder.getRemark());
        update.setUpdateTime(DateUtils.getNowDate());
        update.setUpdateBy(SecurityUtils.getUserId() + "");
        return updateStockOutOrder(update);
    }
}